package com.janyee.buddha.view

import android.content.Context
import android.graphics.*
import android.util.AttributeSet
import android.util.Log
import android.util.TypedValue
import android.view.MotionEvent
import android.widget.TextView

import com.janyee.buddha.entity.LineText
import com.janyee.buddha.listener.BookEventListener
import com.janyee.buddha.listener.BookViewListener

/**
 * Created by kmlixh on 17/12/6.
 * useage:
 * TextTest
 */

class BookViewer : TextView {
    private var topSpacing = 40f
    private var leftSpacing = 0f
    private var longClicked = false

    private var markWidth = 0f
    private var lineHeight = 0f
    private var singleWidth = 0f
    private var lastTouched = PointF(0f, 0f)
    private var startPointF: PointF? = null
    private var endPointF: PointF? = null
    private var startPoint: Point? = null
    private var endPoint: Point? = null
    private var pageType = 0
    private lateinit var pair: Pair<List<LineText>, Int>
    var bookeventListener: BookEventListener? = null
    private lateinit var bookViewListener: BookViewListener
    constructor(context: Context) : super(context) {
        Init()
    }

    constructor(context: Context, attrs: AttributeSet?) : super(context, attrs) {
        Init()
    }

    constructor(context: Context, attrs: AttributeSet?, defStyleAttr: Int) : super(context, attrs, defStyleAttr) {
        Init()
    }

    fun setBookViewListener(bookViewListener: BookViewListener, type: Int) {
        this.pageType = type
        this.bookViewListener = bookViewListener
    }
    private fun Init() {
        setOnTouchListener(onTouchListener)
        markWidth = TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_SP,42f,context.resources.displayMetrics)

        isLongClickable = false


    }


    private fun getLineInfo(): List<LineText> {
        return bookViewListener.getLineInfo(pageType).list
    }

    private fun getPainter(): Painter {
        return bookViewListener.getPainter()
    }

    private var lineCounts: Int = 0

    private var screenWidth: Int = 0

    override fun onDraw(canvas: Canvas) {
        val t1=System.currentTimeMillis()
        screenWidth = (width - 2 * (bookViewListener.getPadding() + bookViewListener.getStartBmp().width)).toInt()
        lineHeight = bookViewListener.getPainter().getLineHeight()
        singleWidth = bookViewListener.getPainter().getSingleWordWidth()
        var counts = (screenWidth / singleWidth).toInt()
        leftSpacing = (screenWidth - counts * singleWidth) / 2 + bookViewListener.getStartBmp().width + bookViewListener.getPadding()
        lineCounts = Math.floor(((height - markWidth + bookViewListener.getLineSpacing()).toDouble() / (lineHeight + bookViewListener.getLineSpacing()))).toInt()
        topSpacing = 0f

        var top = topSpacing
        if (bookViewListener.getLineInfo(pageType).count == 0) {
            if (measuredWidth > 0 && measuredHeight > 0) {
                bookViewListener.onMeasureSize(screenWidth, (height - markWidth + bookViewListener.getLineSpacing()).toInt())
            }
        }
        for (text in getLineInfo()) {
            text.draw(canvas, getPainter(), leftSpacing, top, bookViewListener.getText())
            top += getPainter().getLineHeight() + bookViewListener.getLineSpacing()
        }
        if (longClicked) {
            canvas.drawBitmap(bookViewListener.getStartBmp(), startPointF!!.x - bookViewListener.getStartBmp().width, startPointF!!.y, getPainter().getNormalTextPaint())
            canvas.drawBitmap(bookViewListener.getEndBmp(), endPointF!!.x, endPointF!!.y, getPainter().getNormalTextPaint())
        }
        val t2=System.currentTimeMillis()
        Log.e("+==","draw time:"+(t2-t1))
    }

    fun callLongClick() {
        longClicked = true
        calLine(lastTouched.x, lastTouched.y)
        if (bookeventListener != null) {
            bookeventListener!!.OnChoosedText()
        }
    }
    internal var touchType = -1
    private var offsetX=0f
    private var offsetY=0f
    private val onTouchListener = OnTouchListener { v, event ->
        when (event.action) {
            MotionEvent.ACTION_DOWN -> {
                Log.e("===", "child down:" + pageType)
                lastTouched = PointF(event.x , event.y)
                if (longClicked) {
                    touchType = touchedTag(lastTouched)
                    if(touchType==1){
                        offsetX=Math.abs(startPointF!!.x-event.x)
                        offsetY=Math.abs(event.y-startPointF!!.y)
                    }else if(touchType==2){
                        offsetX=Math.abs(event.x-endPointF!!.x)
                        offsetY=Math.abs(event.y-endPointF!!.y)
                    }
                    Log.e("=====", "touchType:" + touchType)
                }
                longClicked && pageType == 1
            }
            MotionEvent.ACTION_MOVE -> {
                calPoint(event)
            }
            MotionEvent.ACTION_UP -> {
                Log.e("====","point up")
                if(longClicked){
                    calPoint(event)
                    touchType = -1
                    if (startPoint!!.y > endPoint!!.y||(startPoint!!.y==endPoint!!.y&&startPoint!!.x>endPoint!!.x)) {
                        var p = startPoint
                        startPoint = endPoint
                        endPoint = p
                    }
                    if (startPoint!!.x == getLineInfo().get(startPoint!!.y).length()) {//选择末尾了，跳转到下一行开头
                        startPoint!!.y++
                        startPoint!!.x=0
                    }
                    if(startPoint!!.x==endPoint!!.x&&startPoint!!.y==endPoint!!.y){
                        endPoint!!.x++
                    }
                    if(endPoint!!.x==0){
                        endPoint!!.y--
                        endPoint!!.x = getLineInfo().get(endPoint!!.y).length()
                    }
                    calChoosed()
                }
            }
        }
        longClicked && pageType == 1
    }

    private fun calPoint(event: MotionEvent){
        if (touchType == 1) {
            startPoint = getLineColumnOfPosition(event.x + offsetX, event.y - offsetY)
            Log.e("===", "start changed")
            if (startPoint!!.x == endPoint!!.x && startPoint!!.y == endPoint!!.y) {
                if (getLineInfo().get(endPoint!!.y).length() == endPoint!!.x) {
                    startPoint!!.x--
                } else {
                    endPoint!!.x++
                }
            }
            calChoosed()
        } else if (touchType == 2) {
            endPoint = getLineColumnOfPosition(event.x - offsetX, event.y - offsetY)
            Log.e("===", "end changed" + endPoint)
            if (startPoint!!.x == endPoint!!.x && startPoint!!.y == endPoint!!.y) {
                if (0 == endPoint!!.x) {
                    endPoint!!.x++
                } else {
                    startPoint!!.x--
                }
            }
            calChoosed()
        }
    }
    private fun touchedTag(point: PointF): Int {
        if (point.x > startPointF!!.x - markWidth && point.x < startPointF!!.x && point.y > startPointF!!.y - lineHeight && point.y < startPointF!!.y + markWidth) {
            return 1
        } else if (point.x < endPointF!!.x + markWidth && point.x > endPointF!!.x && point.y > endPointF!!.y  && point.y < endPointF!!.y + markWidth) {
            return 2
        }
        return -1
    }

    private fun calChoosed() {
        if(longClicked){
            startPointF = getPositionOfLineColumn(startPoint!!)
            endPointF = getPositionOfLineColumn(endPoint!!)
            var sp=startPoint!!
            var ep=endPoint!!
            if(sp.y>ep.y||(sp.y==ep.y&&sp.x>ep.x)){
                sp=endPoint!!
                ep=startPoint!!
            }
            for (i in 0 until getLineInfo().size) {
                var s = -1
                var e = -1
                if (i > sp.y && i <= ep.y) {
                    s = 0
                }
                var line = getLineInfo().get(i)
                if (i == sp.y) {
                    s = sp.x
                }
                if (i == ep.y) {
                    e = ep.x
                }
                line.choosed(s, e)
            }
        }else{
            for (i in 0 until getLineInfo().size) {
                var line = getLineInfo().get(i)
                line.choosed(-1, -1)
            }
        }
        postInvalidate()
    }

    private fun getLineColumnOfPosition(x: Float, y: Float): Point {
        var lineIndex: Int = ((y - topSpacing) / (bookViewListener.getLineSpacing() + lineHeight)).toInt()
        if (lineIndex < 0) {
            lineIndex = 0
        } else if (lineIndex >= getLineInfo().size) {
            lineIndex = getLineInfo().size - 1
        }
        var columnIndex: Int = ((x - leftSpacing) / singleWidth).toInt()
        if (columnIndex < 0) {
            columnIndex = 0
        } else if (columnIndex > getLineInfo().get(lineIndex).length()) {
            columnIndex = getLineInfo().get(lineIndex).length()
        }
        return Point(columnIndex, lineIndex)
    }
    private fun getPositionOfLineColumn(p: Point): PointF {
        var y = p.y * (lineHeight + bookViewListener.getLineSpacing()) + lineHeight + topSpacing
        var x = p.x * singleWidth + leftSpacing
        return PointF(x, y)
    }

    private fun calLine(x: Float, y: Float) {
        var p = getLineColumnOfPosition(x, y)
        startPoint = p
        endPoint = Point(p.x + 1, p.y)
        calChoosed()
    }
    private fun cleanTags(){
        longClicked=false
    }

    fun cancelChoosed() {
        cleanTags()
        calChoosed()
        postInvalidate()
    }
}
